package com.springboot.frame.mapper.provider;

import com.springboot.frame.Condition;
import com.springboot.frame.schema.Column;
import com.springboot.frame.schema.LogicColumn;
import com.springboot.frame.schema.PrimaryKey;
import com.springboot.frame.schema.Table;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.builder.annotation.ProviderContext;
import org.apache.ibatis.jdbc.SQL;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.Collection;
import static org.apache.commons.lang3.Validate.notNull;

/**
 * SQL处理类
 *
 * @author liheng
 */
public final class DeleteMapperProvider extends AbstractMapperProvider {

    /**
     * 拦截逻辑
     * @param sql
     * @param table
     */
    private void handleLogic(SQL sql, Table table) {
        LogicColumn logicColumn = table.getLogicColumn();
        String tableName = table.getTableName();
        if (logicColumn != null) {
            sql.UPDATE(tableName).SET(logicColumn.getColumnName() + "=" + logicColumn.getDelValue());
        } else {
            sql.DELETE_FROM(tableName);
        }
    }

    /**
     * 根据主键删除
     *
     * @param id
     * @param providerContext
     * @return
     */
    public String deleteById(Serializable id, ProviderContext providerContext) {
        Table table = getTable(providerContext);
        SQL sql = new SQL();
        handleLogic(sql, table);
        PrimaryKey primaryKey = table.getPrimaryKey();
        if (primaryKey != null) {
            if (id == null) {
                sql.WHERE(primaryKey.getColumnName() + " IS NULL");
            } else {
                sql.WHERE(primaryKey.getColumnName() + " = #{" + primaryKey.getPropertyName() + "}");
            }
        }
        return sql.toString();
    }

    public String delete(Condition<?> condition, ProviderContext providerContext)
            throws SQLException, IllegalAccessException {
        notNull(condition, "condition should not be null on deleteByCondition");
        Table table = getTable(providerContext);
        SQL sql = new SQL();
        handleLogic(sql, table);
        Object parameterObject = condition.getParameterObject();
        int count = 0;
        if (parameterObject != null) {
            for (Column column : table.getColumns()) {
                if (column.getField().get(parameterObject) != null) {
                    count++;
                    sql.WHERE(
                            column.getColumnName() + "=#{parameterObject." + column.getPropertyName() + "}");
                }
            }
        }
    if (CollectionUtils.isNotEmpty(condition.getWhere())) {
      for (String item : condition.getWhere()) {
        count++;
        sql.WHERE(item);
      }
    }
        // 自由拼接条件
//        if (CollectionUtils.isNotEmpty(condition.getWhere())) {
//            // 拼接sql条件 sql.WHERE(condition.getWhere().toArray(new String[condition.getWhere().size()]));  对书写方法不友好
//            sql.WHERE(StringUtils.join(condition.getWhere(), separator));
//        }
        if (count == 0) {
            throw new SQLException("could not delete all table data");
        }
        return sql.toString();
    }

    /**
     * 根据主键id批量删除
     *
     * @param params
     * @param providerContext
     * @return
     */
    public String deleteBatchIds(@Param("list") Collection<Serializable> params,
                                 ProviderContext providerContext) {
        if (CollectionUtils.isEmpty(params)) {
            return this.deleteById(null, providerContext);
        }
        Table table = getTable(providerContext);
        StringBuilder ids = new StringBuilder(params.size());
        for (int i = 0; i < params.size(); i++) {
            ids.append("#{list[" + i + "]},");
        }
        SQL sql = new SQL();
        handleLogic(sql, table);
        return sql.WHERE(
                table.getPrimaryKey().getColumnName() + " in (" + ids.deleteCharAt(ids.length() - 1) + ")")
                .toString();
    }


    /**
     * 清空表
     *
     * @param providerContext
     * @return
     */
    public String truncateTable(ProviderContext providerContext) {
        Table table = getTable(providerContext);
        String sql = "Truncate Table " + table.getTableName();
        return sql;
    }

}
